package com.netintech.intelligenceInterface.iflytek.controller.realtimeTranscribe;

import com.netintech.intelligenceInterface.common.StaticBean;
import com.netintech.intelligenceInterface.iflytek.util.AuthUtils;
import lombok.SneakyThrows;
import okhttp3.*;
import okio.ByteString;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.net.URI;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

import static com.netintech.intelligenceInterface.common.StaticBean.URL1;

/**
 * @author lining
 */
@Component
public class WsHandler extends TextWebSocketHandler {

    private static final String AST_URL = "/tuling/ast/v2/";
    private static final String AUTHORIZATION_PAM = "?authorization";

    public static ConcurrentHashMap<String, WebSocketSession> webSocketSessionMap = new ConcurrentHashMap<>();

    public static ConcurrentHashMap<String, WebSocket> flyWebSocketMap = new ConcurrentHashMap<>();

    private static final long TIMEOUT = 50000L;

    public static final OkHttpClient CLIENT = new OkHttpClient().newBuilder()
            .readTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
            .writeTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
            .connectTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
            .build();

    /**
     * 连接建立成功调用的方法
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        CloseStatus status = new CloseStatus(1001, "鉴权未通过！");
        URI uri = session.getUri();
        assert uri != null;
        String path = uri.getPath();
        String query = uri.getQuery();
        if(path == null || query == null ){
            session.close(status);
            return;
        }
        String[] split = query.split("&");
        Map<String, String> map = new HashMap<>();
        for (String string : split) {
            int i = string.indexOf("=");
            String key = string.substring(0, i);
            String value = string.substring(i + 1);
            map.put(key, value);
        }

        boolean auth = true;
        if (!auth) {
            session.close(status);
            return;
        }
        String sessionId = path.substring(2 + StaticBean.REALTIME_TRANSCRIBE.length());
        webSocketSessionMap.put(sessionId, session);
        String url = "ws://172.16.11.211:10001/tuling/ast/v2/" + sessionId;
//        String url = URL1 + AST_URL + sessionId;
        String requestUrl = AuthUtils.assembleRequestUrl(url, StaticBean.API_KEY, StaticBean.API_SECRET);
        Request request = new Request.Builder().url(requestUrl).build();
        WebSocket webSocket = CLIENT.newWebSocket(request, new WebSocketListener() {
            @Override
            public void onOpen(@NotNull WebSocket webSocket, @NotNull Response response) {
                super.onOpen(webSocket, response);
            }

            @SneakyThrows
            @Override
            public void onMessage(@NotNull WebSocket webSocket, @NotNull String text) {
                //收到科大讯飞的返回 发送给前端
                String url = webSocket.request().url().toString();
                int start = url.indexOf(AST_URL) + AST_URL.length();
                int end = url.indexOf(AUTHORIZATION_PAM);
                String sessionID = url.substring(start, end);
                webSocketSessionMap.get(sessionID).sendMessage(new TextMessage(text));
                super.onMessage(webSocket, text);
            }

            @Override
            public void onMessage(@NotNull WebSocket webSocket, @NotNull ByteString bytes) {
            }

            @Override
            public void onClosing(@NotNull WebSocket webSocket, int code, @NotNull String reason) {
                super.onClosing(webSocket, code, reason);
            }

            @Override
            public void onClosed(@NotNull WebSocket webSocket, int code, @NotNull String reason) {

                super.onClosed(webSocket, code, reason);
            }

            @Override
            public void onFailure(@NotNull WebSocket webSocket, @NotNull Throwable t, Response response) {
                super.onFailure(webSocket, t, response);
            }
        });
        flyWebSocketMap.put(sessionId, webSocket);
    }

    /**
     * 连接关闭调用的方法
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        String sessionId = session.getUri().getPath().substring(2 + StaticBean.REALTIME_TRANSCRIBE.length());
        webSocketSessionMap.remove(sessionId);
        WebSocket socket = flyWebSocketMap.get(sessionId);
        socket.close(1001, "正常关闭！");
        flyWebSocketMap.remove(sessionId);
        super.afterConnectionClosed(session, status);
    }

    /**
     * 实现服务器主动推送
     */
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        super.handleTextMessage(session, message);
    }


    /**
     * 收到前端的语音 发送给科大讯飞
     */
    @Override
    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
        ByteBuffer msg = (ByteBuffer) message.getPayload();
        byte[] bytes = new byte[msg.remaining()];
        String sessionId = session.getUri().getPath().substring(2 + StaticBean.REALTIME_TRANSCRIBE.length());
        WebSocket socket = flyWebSocketMap.get(sessionId);
        socket.send(Arrays.toString(bytes));
    }

    /**
     * 连接发生异常后触发的方法，关闭出错会话的连接，和删除在Map集合中的记录
     */
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        if (session.isOpen()) {
            session.close();
        }
    }

}
